// ----------------------------------------------------------------------------
// serialize_dictionary.h
// ----------------------------------------------------------------------------
#pragma once
#include <fw/base/runtime/hash.h>
#include <cstring>

namespace fw
{
	template<typename T> class SerializeDictionary
	{
	private:
		Hash*		m_name;
		T*			m_payLoad;
		T			m_notFoundValue;
		int			m_capacity;
		int			m_count;
		
	public:
		SerializeDictionary(int initialCapacity, T notFoundValue)
		: m_name			(nullptr)
		, m_payLoad			(nullptr)
		, m_notFoundValue	(notFoundValue)
		, m_capacity		(0)
		, m_count			(0)
		{
			Resize(initialCapacity);
		}
		
		~SerializeDictionary()
		{
			if(m_name)   { delete [] m_name;    m_name    = nullptr; }
			if(m_payLoad){ delete [] m_payLoad; m_payLoad = nullptr; }
		}
		
		const T&	FindByName(Hash name) const
		{
			for(int name_i=0; name_i<m_count; ++name_i)
			{
				if(m_name[name_i] == name)
				{
					return m_payLoad[name_i];
				}
			}
			return m_notFoundValue;
		}
		
		const T&	GetByIndex(int index) const
		{
			if(index < m_count)
			{
				return m_payLoad[index];
			}
			return m_notFoundValue;
		}
		
		Hash		GetNameByIndex(int index) const
		{
			if(index < m_count)
			{
				return m_name[index];
			}
			return Hash();
		}
		
		void		Add(Hash name, T payload)
		{
			if(m_count == m_capacity)
			{
				Grow();
			}
			m_name[m_count]    = name;
			m_payLoad[m_count] = payload;
			m_count++;
		}
		
		int			GetCount() const
		{
			return m_count;
		}
		
	private:
		
		void		Resize(int newCapacity)
		{
			T*    oldPayload = m_payLoad;
			Hash* oldName    = m_name;
			
			m_capacity = newCapacity;
			m_count    = (m_capacity < m_count) ? m_capacity : m_count;
			
			m_payLoad  = (m_capacity) ? new T    [m_capacity] : nullptr;
			m_name     = (m_capacity) ? new Hash [m_capacity] : nullptr;
			
			for(int cpy_i=0; cpy_i<m_count; ++cpy_i)
			{
				m_payLoad[cpy_i] = oldPayload[cpy_i];
				m_name   [cpy_i] = oldName   [cpy_i];
			}
			delete [] oldName;
			delete [] oldPayload;
		}
		
		void		Grow()
		{
			if(m_capacity == 0)
			{
				Resize(1);
			}
			else
			{
				Resize(m_capacity*2);
			}
		}
		
	}; // class SerializeDictionary
	
	
} // namespace fw

